package com.learn.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @EnableWebSecurity：开启WebSecurity模式
 */
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    /**
     * 自定义认证策略
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // auth可使用jdbcAuthentication取数据库数据进行认证（一般），但此处为了省去麻烦直接使用inMemoryAuthentication取内存数据进行认证
        // passwordEncoder指定密码加密方式，若不指定则报错There is no PasswordEncoder mapped for the id "null"
        auth.inMemoryAuthentication()
                .passwordEncoder(new BCryptPasswordEncoder())
                .withUser("admin").password(new BCryptPasswordEncoder().encode("888888")).roles("query", "config", "hello")
                .and()
                .withUser("audit").password(new BCryptPasswordEncoder().encode("888888")).roles("config")
                .and()
                .withUser("common").password(new BCryptPasswordEncoder().encode("888888")).roles("hello");
    }
    
    /**
     * 自定义授权策略
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 关闭CSRF攻击，CSRF指攻击者盗用认证信息，以该认证信息进入网站进行恶意请求
        http.csrf().disable();
        
        // 首页页允许所有人访问，功能页只有指定角色才能访问
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/query/**").hasRole("query")
                .antMatchers("/config/**").hasRole("config")
                .antMatchers("/hello/**").hasRole("hello");
        
        // 功能页角色授权失败则默认回到登录页。如果未指定http.loginPage(String)将生成默认的登录页面
        http.formLogin();
        
        // 开启记住我，Cookie默认保存两周
        http.rememberMe();
        
        // 开启注销功能，注销成功跳转到登录页
        http.logout().logoutSuccessUrl("/login");
    }
}
